package com.pzl.hwr.util;

import android.content.Context;
import android.util.Log;

import com.sinovoice.hcicloudsdk.api.HciCloudSys;
import com.sinovoice.hcicloudsdk.api.hwr.HciCloudHwr;
import com.sinovoice.hcicloudsdk.common.AuthExpireTime;
import com.sinovoice.hcicloudsdk.common.HciErrorCode;
import com.sinovoice.hcicloudsdk.common.InitParam;
import com.sinovoice.hcicloudsdk.common.Session;
import com.sinovoice.hcicloudsdk.common.hwr.HwrAssociateWordsResult;
import com.sinovoice.hcicloudsdk.common.hwr.HwrConfig;
import com.sinovoice.hcicloudsdk.common.hwr.HwrInitParam;
import com.sinovoice.hcicloudsdk.common.hwr.HwrRecogResult;
import com.sinovoice.hcicloudsdk.common.hwr.HwrRecogResultItem;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.Locale;


public class HciCloudHwrHelper {

    public static final String TAG = "HciCloudHwrHelper";

    private static HciCloudHwrHelper mHciCloudHwrHelper = null;

    private HciCloudHwrHelper() {

    }

    public static HciCloudHwrHelper getInstance() {
        if (mHciCloudHwrHelper == null) {
            return new HciCloudHwrHelper();
        }
        return mHciCloudHwrHelper;
    }

    /**
     * 手写功能初始化(initCapKeys对应的每个capKey为HWR手写识别下的“离线本地”功能，就是capKey带local的,"云端"就是带cloud的)
     *
     * @param context     上下文
     * @param initCapKeys 使用的capkey，手写单字识别为hwr.local.letter，多字识别为hwr.local.freestylus，联想功能为hwr.local.associateword
     * @return 返回0为成功，其他为失败
     */
    public int initHwr(Context context, ArrayList<String> initCapKeys) {
        String strConfig = getHwrInitParam(context, convertInitCapKeys(initCapKeys));
        Log.d(TAG, " HciCloudHwr.hciHwrInit strConfig = " + strConfig);
        int errorCode = HciCloudHwr.hciHwrInit(strConfig);
        return errorCode;
    }

    /**
     * @param initCapKeys
     * @return
     */
    private String convertInitCapKeys(ArrayList<String> initCapKeys) {
        if (initCapKeys == null || initCapKeys.isEmpty()) return null;
        String capKeys = "";
        for (int i = 0; i <= initCapKeys.size() - 1; i++) {
            if (i == initCapKeys.size() - 1) {
                capKeys += initCapKeys.get(i);
            } else {
                capKeys += initCapKeys.get(i) + ";";
            }
        }
        return capKeys;
    }

    /**
     * 手写识别函数
     *
     * @param data     笔迹坐标
     * @param capkey   使用的capkey，手写单字识别为hwr.local.letter，多字识别为hwr.local.freestylus，联想功能为hwr.local.associateword
     * @param listener 识别结果回调函数
     */
    public void recog(short[] data, String capkey, IHwrListener listener) {
        Session session = new Session();
        String sessionConfig = getHwrSessionParam(capkey);
        Log.d(TAG, "sessionConfig = " + sessionConfig);
        //sessionStart开启一个session
        int errorCode = HciCloudHwr.hciHwrSessionStart(sessionConfig, session);
        if (errorCode != HciErrorCode.HCI_ERR_NONE) {
            Log.e(TAG, "hciHwrSessionStart failed and return " + errorCode);
            HciCloudHwr.hciHwrSessionStop(session);
            return;
        }

        //识别结果类进行初始化
        HwrRecogResult recogResult = new HwrRecogResult();
        //识别的配置串参数可以设置为空，默认就使用sessionConfig配置串参数
        errorCode = HciCloudHwr.hciHwrRecog(session, data, "", recogResult);
        if (errorCode != HciErrorCode.HCI_ERR_NONE) {
            Log.e(TAG, "hciHwrRecog failed and return " + errorCode);
            return;
        } else {
            listener.onHwrResult(convertResult(recogResult));  //把识别结果传给回调监听
        }

        //关闭Session
        errorCode = HciCloudHwr.hciHwrSessionStop(session);
        if (errorCode != HciErrorCode.HCI_ERR_NONE) {
            Log.e(TAG, "hciHwrSessionStop failed and return " + errorCode);
            return;
        }
    }

    private ArrayList<String> convertResult(HwrRecogResult recogResult) {
        ArrayList<String> result = new ArrayList<>();
        if (recogResult != null) {
            ArrayList<HwrRecogResultItem> recogItemList = recogResult
                    .getResultItemList();
            for (int index = 0; index < recogItemList.size(); index++) {
                String strTmp = recogItemList.get(index).getResult();
                result.add(strTmp);
            }
        }
        return result;
    }

    /**
     * 获取授权（在线的能力每次都需联网获取授权，离线的能力在第一次下载授权文件到本地后，之后sdk会自动在本地验证，过期需重新联网获取授权文件）
     *
     * @return true 成功
     */
    private int checkAuth() {
        // 获取系统授权到期时间
        int initResult;
        AuthExpireTime objExpireTime = new AuthExpireTime();
        initResult = HciCloudSys.hciGetAuthExpireTime(objExpireTime);
        if (initResult == HciErrorCode.HCI_ERR_NONE) {
            // 显示授权日期,如用户不需要关注该值,此处代码可忽略
            Date date = new Date(objExpireTime.getExpireTime() * 1000);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd",
                    Locale.CHINA);
            Log.i(TAG, "expire time: " + sdf.format(date));

            if (objExpireTime.getExpireTime() * 1000 < System
                    .currentTimeMillis()) {
                // 获取授权方法, 返回值为错误码
                Log.i(TAG, "expired date");

                initResult = HciCloudSys.hciCheckAuth();
                if (initResult == HciErrorCode.HCI_ERR_NONE) {
                    Log.i(TAG, "checkAuth success");
                    return initResult;
                } else {
                    Log.e(TAG, "checkAuth failed: " + initResult);
                    return initResult;
                }
            } else {
                // 已经成功获取了授权,并且距离授权到期有充足的时间(>7天)
                Log.i(TAG, "checkAuth success");
                return initResult;
            }
        } else if (initResult == HciErrorCode.HCI_ERR_SYS_AUTHFILE_INVALID) {
            // 如果读取Auth文件失败(比如第一次运行,还没有授权文件),则开始获取授权
            Log.i(TAG, "authfile invalid");

            initResult = HciCloudSys.hciCheckAuth();
            if (initResult == HciErrorCode.HCI_ERR_NONE) {
                Log.i(TAG, "checkAuth success");
                return initResult;
            } else {
                Log.e(TAG, "checkAuth failed: " + initResult);
                return initResult;
            }
        } else {
            // 其他失败原因,请根据SDK帮助文档中"常量字段值"中的错误码的含义检查错误所在
            Log.e(TAG, "getAuthExpireTime Error:" + initResult);
            return initResult;
        }
    }

    /**
     * 联想词功能，对str进行联想，返回联想结果
     *
     * @param str       需要联想的字符串
     * @param assCapkey 联想功能对应的capkey。
     * @return
     */
    public String associateWord(String str, String assCapkey, IHwrListener listener) {
        Log.d(TAG, "联想词：" + str);

        checkAuth();

        Session session = new Session();
        String sessionConfig = getAssociateWordSessionParam(assCapkey);

        int errorCode = HciCloudHwr.hciHwrSessionStart(sessionConfig, session);
        if (errorCode != HciErrorCode.HCI_ERR_NONE) {
            Log.e(TAG, "HciCloudHwr.hciHwrSessionStart failed and return " + errorCode);
        }
        HwrAssociateWordsResult hwrAssociateWordsResult = new HwrAssociateWordsResult();

        errorCode = HciCloudHwr.hciHwrAssociateWords(session, sessionConfig, str, hwrAssociateWordsResult);
        if (errorCode != HciErrorCode.HCI_ERR_NONE) {
            Log.e(TAG, "HciCloudHwr.hciHwrAssociateWords failed and return " + errorCode);
        }
        errorCode = HciCloudHwr.hciHwrSessionStop(session);
        if (errorCode != HciErrorCode.HCI_ERR_NONE) {
            Log.e(TAG, "HciCloudHwr.hciHwrSessionStop failed and return " + errorCode);
        }
        ArrayList<String> lists = hwrAssociateWordsResult.getResultList();
        if (lists == null || lists.isEmpty()) return "";
        if (listener != null) listener.onAssociateResult(lists);
        StringBuilder sb = new StringBuilder();
        Iterator<String> iterator = lists.iterator();
        while (iterator.hasNext()) {
            String string = iterator.next();
            sb.append(string).append(",");
        }
        return sb.toString();
    }

    /**
     * 设置联想词的配置参数
     *
     * @param assCapkey 联想词功能所需的capkey，需要设置为 assCapkey=hwr.local.associateword
     * @return 联想词配置的字符串
     */
    private String getAssociateWordSessionParam(String assCapkey) {
        HwrConfig hwrConfig = new HwrConfig();
        hwrConfig.addParam(HwrConfig.SessionConfig.PARAM_KEY_CAP_KEY, assCapkey);
        return hwrConfig.getStringConfig();
    }



    /**
     * 获取手写识别的配置参数
     *
     * @param hwrCapkey 使用的capkey，手写单字识别为hwr.local.letter，多字识别为hwr.local.freestylus
     * @return 返回配置串
     */
    private String getHwrSessionParam(String hwrCapkey) {
        HwrConfig hwrConfig = new HwrConfig();
        hwrConfig.addParam(HwrConfig.SessionConfig.PARAM_KEY_CAP_KEY, hwrCapkey);
        //设置识别结果的候选个数
        hwrConfig.addParam(HwrConfig.ResultConfig.PARAM_KEY_CAND_NUM, "10");
        //设置识别结果的范围
        hwrConfig.addParam(HwrConfig.ResultConfig.PARAM_KEY_RECOG_RANGE, "gbk");
        //设置叠写还是行写 line是行写，overlap是叠写
        hwrConfig.addParam(HwrConfig.InputConfig.PARAM_KEY_SPLIT_MODE, "line");
        return hwrConfig.getStringConfig();
    }

    /**
     * 获取手写的初始化配置参数
     *
     * @param context     上下文
     * @param initCapkeys 使用的capkey，手写单字识别为hwr.local.letter，
     *                    多字识别为hwr.local.freestylus，
     *                    联想功能为hwr.local.associateword
     *                    可以设置多个，中间以分号隔开
     * @return 返回配置串
     */
    private String getHwrInitParam(Context context, String initCapkeys) {
        HwrInitParam initParam = new HwrInitParam();
        initParam.addParam(HwrInitParam.PARAM_KEY_INIT_CAP_KEYS, initCapkeys);
        initParam.addParam(HwrInitParam.PARAM_KEY_FILE_FLAG, "none");
        /*String dataPath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator
                + "sinovoice" + File.separator
                + context.getPackageName() + File.separator
                + "data" + File.separator;
        //多字识别所需的字典文件
        String[] strings = {"wa.system.dct", "wa.user.dct"};
        for (String data : strings) {
            copyAssetsToSdcard(context, data, dataPath);
        }*/
        String dataPath = Util.HciCloudDataPath;
        Log.d(TAG, "dataPath = " + dataPath);
        initParam.addParam(HwrInitParam.PARAM_KEY_DATA_PATH, dataPath);
        return initParam.getStringConfig();
    }


    /**
     * 手写反初始化功能
     *
     * @return 返回0为成功，其他为失败
     */
    public int releaseHwr() {
        return HciCloudHwr.hciHwrRelease();
    }

}
